#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Chat2AI - 基于通义千问Qwen系列模型的本地终端对话应用

功能特性:
- 多轮对话上下文管理
- 思考过程可视化
- 流式输出支持
- 对话历史记录管理
- 多行输入编辑器
- 配置管理
- 安全密钥管理

作者：Pinocchio
版本：1.0.0
日期：2025-09-23
"""

import os
import sys
import argparse
import configparser
import logging
import json
import time
import hashlib
import re
import subprocess
from datetime import datetime
from typing import List, Dict, Any, Optional, Tuple
from pathlib import Path
import traceback

# 第三方库导入
try:
    from openai import OpenAI
    from cryptography.fernet import Fernet
    from colorama import init, Fore, Style
    import psutil
except ImportError as e:
    print(f"缺少必要的依赖库: {e}")
    print("请运行: pip install openai>=1.0.0 cryptography>=41.0.0 colorama>=0.4.6 psutil>=5.9.0")
    sys.exit(1)

# 初始化colorama
init(autoreset=True)

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('chat2ai.log', encoding='utf-8'),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)


class SecurityManager:
    """安全管理器 - 负责输入过滤、安全内存清除和API密钥加密"""
    
    def __init__(self):
        """初始化安全管理器"""
        self.key = Fernet.generate_key()
        self.cipher_suite = Fernet(self.key)
        logger.info("安全管理器初始化完成")
    
    def filter_input(self, text: str) -> str:
        """
        过滤用户输入，防止SQL注入、XSS攻击和命令注入
        
        Args:
            text (str): 用户输入文本
            
        Returns:
            str: 过滤后的文本
        """
        # 移除潜在的危险字符
        # SQL注入防护
        sql_keywords = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER', 'EXEC']
        filtered_text = text
        for keyword in sql_keywords:
            filtered_text = re.sub(r'(?i)\b' + keyword + r'\b', '', filtered_text)
        
        # XSS防护 - 移除HTML标签
        filtered_text = re.sub(r'<[^>]*>', '', filtered_text)
        
        # 命令注入防护 - 移除命令分隔符
        command_chars = [';', '&', '|', '`', '$(', '&&', '||']
        for char in command_chars:
            filtered_text = filtered_text.replace(char, '')
        
        logger.debug(f"输入过滤完成: {text} -> {filtered_text}")
        return filtered_text
    
    def encrypt_api_key(self, api_key: str) -> str:
        """
        加密API密钥
        
        Args:
            api_key (str): 明文API密钥
            
        Returns:
            str: 加密后的API密钥
        """
        encrypted_key = self.cipher_suite.encrypt(api_key.encode())
        logger.debug("API密钥加密完成")
        return encrypted_key.decode()
    
    def decrypt_api_key(self, encrypted_api_key: str) -> str:
        """
        解密API密钥
        
        Args:
            encrypted_api_key (str): 加密的API密钥
            
        Returns:
            str: 解密后的API密钥
        """
        decrypted_key = self.cipher_suite.decrypt(encrypted_api_key.encode())
        logger.debug("API密钥解密完成")
        return decrypted_key.decode()
    
    def secure_clear_memory(self, data: str) -> None:
        """
        安全清除内存中的敏感数据
        
        Args:
            data (str): 要清除的数据
        """
        # 在Python中，我们无法直接控制内存清除，但可以通过重写变量来降低风险
        data = "0" * len(data)
        del data
        logger.debug("内存安全清除完成")


class ConfigManager:
    """配置管理器 - 负责配置加载、管理和验证"""
    
    def __init__(self, config_path: str = "config.ini"):
        """
        初始化配置管理器
        
        Args:
            config_path (str): 配置文件路径
        """
        self.config_path = config_path
        self.config = configparser.ConfigParser()
        self.security_manager = SecurityManager()
        self.load_config()
        logger.info("配置管理器初始化完成")
    
    def load_config(self) -> None:
        """从文件加载配置"""
        # 如果配置文件不存在，创建默认配置
        if not os.path.exists(self.config_path):
            self.create_default_config()
        
        self.config.read(self.config_path, encoding='utf-8')
        logger.info(f"配置文件加载完成: {self.config_path}")
    
    def create_default_config(self) -> None:
        """创建默认配置文件"""
        self.config['DEFAULT'] = {
            'BASE_URL': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
            'API_KEY': 'your_api_key_here',
            'MODEL_NAME': 'qwen-plus-latest',
            'TEMPERATURE': '0.7',
            'PRESENCE_PENALTY': '0.1',
            'FREQUENCY_PENALTY': '0.1',
            'MAX_TOKENS': '32768',
            'STREAM': 'true',
            'ENABLE_THINKING': 'true'
        }
        
        with open(self.config_path, 'w', encoding='utf-8') as configfile:
            self.config.write(configfile)
        logger.info(f"默认配置文件已创建: {self.config_path}")
    
    def get_config(self, section: str = 'DEFAULT', key: str = None) -> Any:
        """
        获取配置值
        
        Args:
            section (str): 配置节
            key (str): 配置键
            
        Returns:
            Any: 配置值
        """
        if key is None:
            return dict(self.config[section])
        return self.config.get(section, key)
    
    def set_config(self, section: str, key: str, value: str) -> None:
        """
        设置配置值
        
        Args:
            section (str): 配置节
            key (str): 配置键
            value (str): 配置值
        """
        if not self.config.has_section(section) and section != 'DEFAULT':
            self.config.add_section(section)
        self.config.set(section, key, value)
        
        # 保存到文件
        with open(self.config_path, 'w', encoding='utf-8') as configfile:
            self.config.write(configfile)
        logger.info(f"配置已更新: [{section}] {key} = {value}")
    
    def validate_config(self) -> bool:
        """
        验证配置是否有效
        
        Returns:
            bool: 验证结果
        """
        required_keys = ['base_url', 'api_key', 'model_name']
        for key in required_keys:
            try:
                if not self.config.get('DEFAULT', key):
                    logger.error(f"缺少必要配置项: {key}")
                    return False
            except Exception:
                logger.error(f"缺少必要配置项: {key}")
                return False
        return True


class MetricsCollector:
    """指标收集器 - 收集请求计数、token使用、响应时间等性能指标"""
    
    def __init__(self):
        """初始化指标收集器"""
        self.request_count = 0
        self.total_tokens = 0
        self.start_time = time.time()
        logger.info("指标收集器初始化完成")
    
    def record_request(self) -> None:
        """记录请求次数"""
        self.request_count += 1
        logger.debug(f"请求次数记录: {self.request_count}")
    
    def record_tokens(self, tokens: int) -> None:
        """
        记录token使用量
        
        Args:
            tokens (int): 使用的token数量
        """
        self.total_tokens += tokens
        logger.debug(f"Token使用量记录: {tokens}, 总计: {self.total_tokens}")
    
    def get_metrics(self) -> Dict[str, Any]:
        """
        获取性能指标
        
        Returns:
            Dict[str, Any]: 性能指标字典
        """
        uptime = time.time() - self.start_time
        metrics = {
            'request_count': self.request_count,
            'total_tokens': self.total_tokens,
            'uptime_seconds': uptime,
            'requests_per_minute': self.request_count / (uptime / 60) if uptime > 0 else 0
        }
        logger.debug(f"获取性能指标: {metrics}")
        return metrics


class HistoryManager:
    """历史记录管理器 - 负责对话记录的保存、加载和搜索"""
    
    def __init__(self, history_dir: str = "history"):
        """
        初始化历史记录管理器
        
        Args:
            history_dir (str): 历史记录目录
        """
        self.history_dir = Path(history_dir)
        self.history_dir.mkdir(exist_ok=True)
        logger.info(f"历史记录管理器初始化完成，目录: {self.history_dir}")
    
    def save_history(self, messages: List[Dict[str, str]], filename: str = None) -> str:
        """
        保存对话历史记录为Markdown格式
        
        Args:
            messages (List[Dict[str, str]]): 对话消息列表
            filename (str): 文件名（可选）
            
        Returns:
            str: 保存的文件路径
        """
        if not filename:
            timestamp = int(time.time())
            filename = f"{timestamp}.md"
        
        filepath = self.history_dir / filename
        
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(f"# 对话历史记录\n\n")
            f.write(f"创建时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
            
            for msg in messages:
                role = msg.get('role', 'unknown')
                content = msg.get('content', '')
                
                if role == 'user':
                    f.write(f"## 用户:\n\n{content}\n\n")
                elif role == 'assistant':
                    # 处理思考过程可视化
                    if '<thinking>' in content and '</thinking>' in content:
                        parts = content.split('<thinking>')
                        f.write(f"## AI助手:\n\n")
                        f.write(f"{parts[0]}\n\n")
                        
                        thinking_parts = parts[1].split('</thinking>')
                        f.write(f"### 思考过程:\n\n{thinking_parts[0]}\n\n")
                        
                        if len(thinking_parts) > 1 and thinking_parts[1].strip():
                            f.write(f"### 答案:\n\n{thinking_parts[1].strip()}\n\n")
                    else:
                        f.write(f"## AI助手:\n\n{content}\n\n")
                else:
                    f.write(f"## {role}:\n\n{content}\n\n")
        
        logger.info(f"对话历史记录已保存: {filepath}")
        return str(filepath)
    
    def load_history(self, filename: str) -> List[Dict[str, str]]:
        """
        加载对话历史记录
        
        Args:
            filename (str): 文件名
            
        Returns:
            List[Dict[str, str]]: 对话消息列表
        """
        filepath = self.history_dir / filename
        messages = []
        
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()
                
            # 简单解析Markdown内容
            lines = content.split('\n')
            current_role = None
            current_content = []
            
            for line in lines:
                if line.startswith('## 用户:'):
                    if current_role and current_content:
                        messages.append({'role': current_role, 'content': '\n'.join(current_content)})
                    current_role = 'user'
                    current_content = []
                elif line.startswith('## AI助手:'):
                    if current_role and current_content:
                        messages.append({'role': current_role, 'content': '\n'.join(current_content)})
                    current_role = 'assistant'
                    current_content = []
                elif line.startswith('## '):
                    if current_role and current_content:
                        messages.append({'role': current_role, 'content': '\n'.join(current_content)})
                    current_role = 'system'
                    current_content = []
                elif line.strip() and not line.startswith('#'):
                    current_content.append(line)
            
            # 添加最后一条消息
            if current_role and current_content:
                messages.append({'role': current_role, 'content': '\n'.join(current_content)})
                
            logger.info(f"对话历史记录已加载: {filepath}")
        except Exception as e:
            logger.error(f"加载历史记录失败: {e}")
            
        return messages
    
    def list_history(self) -> List[str]:
        """
        列出所有历史记录文件
        
        Returns:
            List[str]: 历史记录文件列表
        """
        files = list(self.history_dir.glob("*.md"))
        filenames = [f.name for f in files]
        logger.debug(f"历史记录文件列表: {filenames}")
        return filenames
    
    def search_history(self, keyword: str) -> List[Tuple[str, str]]:
        """
        搜索历史记录
        
        Args:
            keyword (str): 搜索关键词
            
        Returns:
            List[Tuple[str, str]]: 匹配的文件名和内容摘要
        """
        results = []
        files = self.history_dir.glob("*.md")
        
        for file_path in files:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                    if keyword.lower() in content.lower():
                        # 提取内容摘要
                        lines = content.split('\n')
                        summary = '\n'.join(lines[:5])  # 前5行作为摘要
                        results.append((file_path.name, summary))
            except Exception as e:
                logger.error(f"搜索历史记录时读取文件失败 {file_path}: {e}")
        
        logger.info(f"历史记录搜索完成，关键词: {keyword}，结果数: {len(results)}")
        return results


class ChatSession:
    """会话管理器 - 管理与AI模型的对话会话"""
    
    def __init__(self, config_manager: ConfigManager):
        """
        初始化会话管理器
        
        Args:
            config_manager (ConfigManager): 配置管理器实例
        """
        self.config_manager = config_manager
        self.messages = []
        self.client = None
        self.metrics_collector = MetricsCollector()
        self.initialize_client()
        logger.info("会话管理器初始化完成")
    
    def initialize_client(self) -> None:
        """初始化OpenAI客户端"""
        try:
            base_url = self.config_manager.get_config('DEFAULT', 'BASE_URL')
            api_key = self.config_manager.get_config('DEFAULT', 'API_KEY')
            
            self.client = OpenAI(
                base_url=base_url,
                api_key=api_key
            )
            logger.info("OpenAI客户端初始化完成")
        except Exception as e:
            logger.error(f"OpenAI客户端初始化失败: {e}")
    
    def add_message(self, role: str, content: str) -> None:
        """
        添加消息到对话历史
        
        Args:
            role (str): 消息角色 (user, assistant, system)
            content (str): 消息内容
        """
        self.messages.append({'role': role, 'content': content})
        logger.debug(f"消息已添加: {role} -> {content[:50]}...")
    
    def get_messages(self) -> List[Dict[str, str]]:
        """
        获取对话历史消息
        
        Returns:
            List[Dict[str, str]]: 对话消息列表
        """
        return self.messages.copy()
    
    def clear_messages(self) -> None:
        """清空对话历史"""
        self.messages.clear()
        logger.info("对话历史已清空")
    
    def chat_with_ai(self, user_input: str) -> str:
        """
        与AI进行对话
        
        Args:
            user_input (str): 用户输入
            
        Returns:
            str: AI回复
        """
        # 添加用户消息到历史
        self.add_message('user', user_input)
        
        # 获取配置参数
        model_name = self.config_manager.get_config('DEFAULT', 'MODEL_NAME')
        temperature = float(self.config_manager.get_config('DEFAULT', 'TEMPERATURE'))
        max_tokens = int(self.config_manager.get_config('DEFAULT', 'MAX_TOKENS'))
        presence_penalty = float(self.config_manager.get_config('DEFAULT', 'PRESENCE_PENALTY'))
        frequency_penalty = float(self.config_manager.get_config('DEFAULT', 'FREQUENCY_PENALTY'))
        stream = self.config_manager.get_config('DEFAULT', 'STREAM').lower() == 'true'
        enable_thinking = self.config_manager.get_config('DEFAULT', 'ENABLE_THINKING').lower() == 'true'
        
        # 记录请求
        self.metrics_collector.record_request()
        
        try:
            # 构建系统提示词
            system_prompt = "你是一个智能AI助手。"
            if enable_thinking:
                system_prompt += "请在<thinking>标签内展示你的思考过程，在<answer>标签内提供最终答案。"
            
            # 确保系统消息在消息列表开头
            if not self.messages or self.messages[0]['role'] != 'system':
                self.messages.insert(0, {'role': 'system', 'content': system_prompt})
            
            # 调用AI API
            response = self.client.chat.completions.create(
                model=model_name,
                messages=self.messages,
                temperature=temperature,
                max_tokens=max_tokens,
                presence_penalty=presence_penalty,
                frequency_penalty=frequency_penalty,
                stream=stream
            )
            
            if stream:
                # 流式输出处理
                full_response = ""
                for chunk in response:
                    if chunk.choices and chunk.choices[0].delta.content:
                        content = chunk.choices[0].delta.content
                        full_response += content
                        print(content, end='', flush=True)
                print()  # 换行
                # 添加AI回复到历史
                self.add_message('assistant', full_response)
                # 记录token使用
                if hasattr(response, 'usage') and response.usage:
                    self.metrics_collector.record_tokens(response.usage.total_tokens)
                return full_response
            else:
                # 非流式输出处理
                ai_response = response.choices[0].message.content
                print(ai_response)
                # 添加AI回复到历史
                self.add_message('assistant', ai_response)
                # 记录token使用
                if hasattr(response, 'usage') and response.usage:
                    self.metrics_collector.record_tokens(response.usage.total_tokens)
                return ai_response
                
        except Exception as e:
            error_msg = f"与AI对话时发生错误: {str(e)}"
            logger.error(error_msg)
            return error_msg


class CLIInterface:
    """CLI界面 - 提供命令行用户界面"""
    
    def __init__(self, config_manager: ConfigManager, chat_session: ChatSession, history_manager: HistoryManager):
        """
        初始化CLI界面
        
        Args:
            config_manager (ConfigManager): 配置管理器实例
            chat_session (ChatSession): 会话管理器实例
            history_manager (HistoryManager): 历史记录管理器实例
        """
        self.config_manager = config_manager
        self.chat_session = chat_session
        self.history_manager = history_manager
        self.multiline_buffer = []
        logger.info("CLI界面初始化完成")
    
    def display_welcome(self) -> None:
        """显示欢迎信息"""
        print(Fore.CYAN + "=" * 60)
        print(Fore.CYAN + "🚀 欢迎使用 Chat2AI - 基于通义千问的智能对话应用")
        print(Fore.CYAN + "=" * 60)
        print(Fore.GREEN + "📝 支持多行输入，按 Enter 换行，输入 /:submit 提交内容")
        print(Fore.GREEN + "❓ 输入 /:help 查看帮助信息")
        print(Fore.GREEN + "👋 输入 /:exit 退出程序")
        print(Fore.CYAN + "=" * 60)
    
    def display_help(self) -> None:
        """显示帮助信息"""
        help_text = f"""
{Fore.CYAN}🤖 Chat2AI 帮助信息
{Fore.CYAN}{"=" * 40}
{Fore.YELLOW}📌 基本操作:
  直接输入文本        - 添加到输入缓冲区
  /:submit           - 提交所有输入内容给AI模型

{Fore.YELLOW}🔧 常用命令:
  /:help             - 显示帮助信息
  /:exit             - 退出程序
  /:clear            - 清空对话历史
  /:reset            - 重置会话
  /:config           - 查看当前配置
  /:metrics          - 显示性能指标

{Fore.YELLOW}💾 历史记录:
  /:save             - 保存当前会话
  /:load <文件名>    - 加载历史会话
  /:history          - 查看历史记录文件
  /:search <关键词>  - 搜索历史记录

{Fore.YELLOW}⚙️  配置管理:
  /:set <参数> <值>  - 设置配置参数
  /:get <参数>       - 获取配置参数
        """
        print(help_text)
    
    def handle_command(self, command: str) -> bool:
        """
        处理用户命令
        
        Args:
            command (str): 用户命令
            
        Returns:
            bool: 是否继续运行程序
        """
        command = command.strip().lower()
        
        if command == '/:exit':
            print(Fore.GREEN + "👋 再见！感谢使用 Chat2AI")
            return False
        elif command == '/:help':
            self.display_help()
        elif command == '/:clear':
            self.chat_session.clear_messages()
            print(Fore.GREEN + "✅ 对话历史已清空")
        elif command == '/:config':
            config = self.config_manager.get_config()
            print(Fore.CYAN + "⚙️  当前配置:")
            for key, value in config.items():
                # 隐藏API密钥的实际值
                if key.lower() == 'api_key' and value != 'your_api_key_here':
                    print(f"{Fore.YELLOW}  {key}: {'*' * len(value)}")
                else:
                    print(f"{Fore.YELLOW}  {key}: {value}")
        elif command == '/:history':
            files = self.history_manager.list_history()
            if files:
                print(Fore.CYAN + "📚 历史记录文件:")
                for i, file in enumerate(files, 1):
                    print(f"{Fore.YELLOW}  {i}. {file}")
            else:
                print(Fore.YELLOW + "📭 暂无历史记录文件")
        elif command == '/:reset':
            self.chat_session.clear_messages()
            print(Fore.GREEN + "🔄 会话已重置")
        elif command.startswith('/:save'):
            try:
                messages = self.chat_session.get_messages()
                if messages:
                    filepath = self.history_manager.save_history(messages)
                    print(Fore.GREEN + f"✅ 会话已保存至: {filepath}")
                else:
                    print(Fore.YELLOW + "📭 暂无对话内容可保存")
            except Exception as e:
                print(Fore.RED + f"❌ 保存会话失败: {e}")
        elif command.startswith('/:load '):
            try:
                filename = command[7:].strip()
                messages = self.history_manager.load_history(filename)
                self.chat_session.clear_messages()
                self.chat_session.messages.extend(messages)
                print(Fore.GREEN + f"✅ 会话已加载: {filename}")
            except Exception as e:
                print(Fore.RED + f"❌ 加载会话失败: {e}")
        elif command.startswith('/:search '):
            try:
                keyword = command[9:].strip()
                results = self.history_manager.search_history(keyword)
                if results:
                    print(Fore.CYAN + f"🔍 搜索结果 (关键词: '{keyword}'):")
                    for i, (filename, summary) in enumerate(results, 1):
                        print(f"{Fore.YELLOW}  {i}. {filename}: {summary[:100]}...")
                else:
                    print(Fore.YELLOW + f"📭 未找到包含关键词 '{keyword}' 的历史记录")
            except Exception as e:
                print(Fore.RED + f"❌ 搜索历史记录失败: {e}")
        elif command.startswith('/:set '):
            try:
                parts = command[6:].strip().split(' ', 1)
                if len(parts) == 2:
                    key, value = parts
                    self.config_manager.set_config('DEFAULT', key.upper(), value)
                    print(Fore.GREEN + f"✅ 配置已更新: {key} = {value}")
                    
                    # 如果是API密钥或BASE_URL相关配置，重新初始化客户端
                    if key.upper() in ['API_KEY', 'BASE_URL']:
                        self.chat_session.initialize_client()
                else:
                    print(Fore.RED + "❌ 命令格式错误，请使用 /:set <参数> <值>")
            except Exception as e:
                print(Fore.RED + f"❌ 设置配置失败: {e}")
        elif command.startswith('/:get '):
            try:
                key = command[6:].strip().upper()
                value = self.config_manager.get_config('DEFAULT', key)
                # 隐藏API密钥的实际值
                if key.lower() == 'api_key' and value != 'your_api_key_here':
                    print(f"{Fore.YELLOW}{key}: {'*' * len(value)}")
                else:
                    print(f"{Fore.YELLOW}{key}: {value}")
            except Exception as e:
                print(Fore.RED + f"❌ 获取配置失败: {e}")
        elif command == '/:submit':
            if self.multiline_buffer:
                user_input = '\n'.join(self.multiline_buffer)
                self.multiline_buffer.clear()
                self.process_user_input(user_input)
                print(Fore.YELLOW + "\n📝 请继续输入，输入 /:submit 提交")
            else:
                print(Fore.YELLOW + "📭 输入缓冲区为空")
        elif command == '/:metrics':
            metrics = self.chat_session.metrics_collector.get_metrics()
            print(Fore.CYAN + "📊 性能指标:")
            for key, value in metrics.items():
                if 'tokens' in key or 'count' in key:
                    print(f"{Fore.YELLOW}  {key}: {value}")
                else:
                    print(f"{Fore.YELLOW}  {key}: {value:.2f}")
        else:
            print(Fore.RED + f"❓ 未知命令: {command}，输入 /:help 查看帮助")
        
        return True
    
    def process_user_input(self, user_input: str) -> None:
        """
        处理用户输入
        
        Args:
            user_input (str): 用户输入内容
        """
        # 过滤用户输入
        filtered_input = self.config_manager.security_manager.filter_input(user_input)
        
        # 显示用户输入
        print(f"{Fore.BLUE}👤 用户:")
        # 如果是多行输入，保持格式
        if '\n' in filtered_input:
            lines = filtered_input.split('\n')
            for line in lines:
                print(f"{Fore.BLUE}   {line}")
        else:
            print(f"{Fore.BLUE}   {filtered_input}")
        
        # 与AI对话
        print(Fore.MAGENTA + "🤖 AI助手:", end=' ')
        ai_response = self.chat_session.chat_with_ai(filtered_input)
        
        # 思考过程可视化处理
        if '<thinking>' in ai_response and '</thinking>' in ai_response:
            parts = ai_response.split('<thinking>')
            if parts[0].strip():
                print(Fore.MAGENTA + parts[0].strip())
            
            thinking_parts = parts[1].split('</thinking>')
            print(Fore.YELLOW + "\n💡 [思考过程]")
            thinking_content = thinking_parts[0].strip()
            if '\n' in thinking_content:
                lines = thinking_content.split('\n')
                for line in lines:
                    print(Fore.YELLOW + f"   {line}")
            else:
                print(Fore.YELLOW + f"   {thinking_content}")
            
            if len(thinking_parts) > 1 and thinking_parts[1].strip():
                print(Fore.MAGENTA + "\n✅ [答案]")
                answer_content = thinking_parts[1].strip()
                if '\n' in answer_content:
                    lines = answer_content.split('\n')
                    for line in lines:
                        print(Fore.MAGENTA + f"   {line}")
                else:
                    print(Fore.MAGENTA + f"   {answer_content}")
        print()  # 添加空行以分隔对话
    
    def run(self) -> None:
        """运行CLI界面主循环"""
        self.display_welcome()
        
        print(Fore.YELLOW + "📝 请开始输入，输入 /:submit 提交内容")
        
        while True:
            try:
                # 获取用户输入（无提示符）
                user_input = input()
                
                # 检查特殊命令
                if user_input.strip() == '/:submit':
                    if self.multiline_buffer:
                        full_input = '\n'.join(self.multiline_buffer)
                        self.multiline_buffer.clear()
                        self.process_user_input(full_input)
                        print(Fore.YELLOW + "\n📝 请继续输入，输入 /:submit 提交")
                    else:
                        print(Fore.YELLOW + "📭 输入缓冲区为空")
                    continue
                elif user_input.strip() == '/:help':
                    self.display_help()
                    print(Fore.YELLOW + "\n📝 请继续输入，输入 /:submit 提交")
                    continue
                elif user_input.strip() == '/:exit':
                    print(Fore.GREEN + "👋 再见！感谢使用 Chat2AI")
                    break
                elif user_input.strip().startswith('/:'):
                    # 处理其他命令
                    if not self.handle_command(user_input):
                        break
                    print(Fore.YELLOW + "\n📝 请继续输入，输入 /:submit 提交")
                    continue
                else:
                    # 添加到输入缓冲区
                    self.multiline_buffer.append(user_input)
                    continue
                    
            except KeyboardInterrupt:
                if self.multiline_buffer:
                    print(Fore.YELLOW + "\n\n↩️  检测到 Ctrl+C，是否要清空当前输入? (y/n)")
                    try:
                        confirm = input().strip().lower()
                        if confirm in ['y', 'yes', '是']:
                            self.multiline_buffer.clear()
                            print(Fore.YELLOW + "↩️  输入已清空")
                        else:
                            print(Fore.YELLOW + "📝 继续输入")
                    except:
                        self.multiline_buffer.clear()
                        print(Fore.YELLOW + "\n↩️  输入已清空")
                else:
                    print(Fore.YELLOW + "\n\n👋 检测到 Ctrl+C，输入 /:exit 退出程序")
            except EOFError:
                print(Fore.GREEN + "\n👋 再见！")
                break
            except Exception as e:
                logger.error(f"处理用户输入时发生错误: {e}")
                print(Fore.RED + f"❌ 发生错误: {e}")


def init_config() -> None:
    """初始化配置文件"""
    config_manager = ConfigManager()
    print(Fore.GREEN + f"默认配置文件已创建: {config_manager.config_path}")
    print(Fore.YELLOW + "请编辑配置文件或使用命令行参数设置API密钥")


def set_api_key(api_key: str) -> None:
    """设置API密钥"""
    config_manager = ConfigManager()
    # 加密API密钥（可选）
    # encrypted_key = config_manager.security_manager.encrypt_api_key(api_key)
    # config_manager.set_config('DEFAULT', 'API_KEY', encrypted_key)
    config_manager.set_config('DEFAULT', 'API_KEY', api_key)
    print(Fore.GREEN + "API密钥已设置")


def set_base_url(base_url: str) -> None:
    """设置基础URL"""
    config_manager = ConfigManager()
    config_manager.set_config('DEFAULT', 'BASE_URL', base_url)
    print(Fore.GREEN + "基础URL已设置")


def set_model(model: str) -> None:
    """设置模型"""
    config_manager = ConfigManager()
    config_manager.set_config('DEFAULT', 'MODEL_NAME', model)
    print(Fore.GREEN + "模型已设置")


def main():
    """主函数"""
    # 命令行参数解析
    parser = argparse.ArgumentParser(description='Chat2AI - 基于通义千问的智能对话应用')
    parser.add_argument('--init', action='store_true', help='初始化配置文件')
    parser.add_argument('--api_key', type=str, help='设置API密钥')
    parser.add_argument('--base_url', type=str, help='设置基础URL')
    parser.add_argument('--model', type=str, help='设置模型名称')
    parser.add_argument('--config', type=str, help='指定配置文件路径')
    parser.add_argument('--temperature', type=float, help='设置温度参数')
    parser.add_argument('--max_tokens', type=int, help='设置最大token数')
    parser.add_argument('--presence_penalty', type=float, help='设置存在惩罚')
    parser.add_argument('--frequency_penalty', type=float, help='设置频率惩罚')
    parser.add_argument('--stream', type=str, help='是否启用流式输出(true/false)')
    parser.add_argument('--enable_thinking', type=str, help='是否启用思考过程可视化(true/false)')
    
    args = parser.parse_args()
    
    # 处理初始化命令
    if args.init:
        init_config()
        return
    
    # 处理API密钥设置
    if args.api_key:
        set_api_key(args.api_key)
        return
    
    # 处理基础URL设置
    if args.base_url:
        set_base_url(args.base_url)
        return
    
    # 处理模型设置
    if args.model:
        set_model(args.model)
        return
    
    # 创建核心组件
    try:
        config_path = args.config if args.config else "config.ini"
        config_manager = ConfigManager(config_path)
        
        # 设置其他配置参数
        if args.temperature is not None:
            config_manager.set_config('DEFAULT', 'TEMPERATURE', str(args.temperature))
        if args.max_tokens is not None:
            config_manager.set_config('DEFAULT', 'MAX_TOKENS', str(args.max_tokens))
        if args.presence_penalty is not None:
            config_manager.set_config('DEFAULT', 'PRESENCE_PENALTY', str(args.presence_penalty))
        if args.frequency_penalty is not None:
            config_manager.set_config('DEFAULT', 'FREQUENCY_PENALTY', str(args.frequency_penalty))
        if args.stream is not None:
            config_manager.set_config('DEFAULT', 'STREAM', args.stream.lower())
        if args.enable_thinking is not None:
            config_manager.set_config('DEFAULT', 'ENABLE_THINKING', args.enable_thinking.lower())
        
        # 验证配置
        if not config_manager.validate_config():
            print(Fore.RED + "配置验证失败，请检查配置文件")
            return
        
        chat_session = ChatSession(config_manager)
        history_manager = HistoryManager()
        cli_interface = CLIInterface(config_manager, chat_session, history_manager)
        
        # 运行CLI界面
        cli_interface.run()
        
    except Exception as e:
        logger.error(f"程序运行时发生错误: {e}")
        traceback.print_exc()
        print(Fore.RED + f"程序运行时发生错误: {e}")


if __name__ == "__main__":
    main()
